<?php
/**
 * 上传工具
 * 2019年10月28日11:54:27
 * ZJY
 */
namespace phpless\ORG;

class Uploader
{
    // 上传路径
    public $root_path;
    // 文件类型
    public $file_types;
    // 子目录类型
    public $sub_path_type;
    public $error=array(
        0=>'上传成功',
        1=>'上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值',
        2=>'上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值',
        3=>'文件只有部分被上传',
        4=>'没有文件被上传',
        5=>'上传文件的类型未指定', # 此错误码已被官方废弃，本上传类用于所上传的文件类型被禁止
        6=>'找不到临时文件夹',
        7=>'文件写入失败',
    );
    // 初始化
    public function __construct($file_types=null,$sub_path_type=1)
    {
        // 定义上传路径
        $this->root_path=UPLOADS_PATH;
        // 定义文件类型
        if(empty($file_types)){
            $file_types=array('png','gif','jpg','jpeg');
        }
        if(is_string($file_types)){
            $file_types=explode(',',$file_types);
        }
        $this->file_types=$file_types;
        // 是否开启子路径 0、不开启，1、开启类型一子目录，2、开启类型二子目录
        $this->sub_path_type=in_array($sub_path_type,[0,1,2])?$sub_path_type:0;
    }
    // 检测上传目录是否存在，不存在则创建
    public function checkUploadsPath($uploads_path)
    {
        $result=true;
        if(!is_dir($uploads_path)){
            $result=mkdir($uploads_path,0755,true);
        }
        return $result;
    }
    // 检测上传文件类型
    public function checkFileType($file_type)
    {
        return in_array($file_type,$this->file_types)?true:false;
    }
    // 重新格式化上传文件数组
    public function resetFILES($files)
    {
        $result=false;
        if(!is_array($files) && count($files)<=0){
            return $result;
        }
        foreach($files as $item=>$vo){
            // 判断上传文件数组的类型
            if(is_array($vo['error'])){
                foreach($vo as $k=>$v){
                    // 分散各组值到相应的数组中
                    foreach($v as $key=>$value){
                        $key_temp=$item.'_'.$key;
                        $result[$key_temp][$k]=$value;
                    }

                }
            }else{
                $result[$item]=$vo;
            }

        }
        unset($files);
        unset($item);
        unset($k);
        unset($key);
        unset($vo);
        unset($v);
        unset($value);
        unset($item);
        return $result;
    }
    // 上传多个文件 返回值：数组 文件名称、文件相对路径、回执信息、上传结果
    public function uploads($files)
    {
        $result=array(
            'status'=>0,
            'info'=>'上传失败',
            'data'=>[],
        );
        // 判断传入参数
        if(!is_array($files)){
            $result['info']='上传失败，传参有误、此参数需要为数组';
            return $result;
        }
        // 格式化参数
        $files=$this->resetFILES($files);
        // 定义上传总状态
        $status=0;
        foreach($files as $k=>$v){
            $ret=$this->uploadOne($v);
            $result['data'][$k] = $ret;
            $status = $status + $ret['status'];
        }
        $result['status']=$status;
        $result['info']=$status?'上传成功':'上传失败';
        return $result;
    }
    // 上传单个文件 返回值：文件名称、文件相对路径、回执信息、上传结果
    public function uploadOne($files)
    {
        $result=array(
            'status'=>0,
            'info'=>'上传失败',
            'file_ext'=>'',
            'file_name'=>'',
            'file_path'=>'',
        );
        // 判断传参是否正确
        if(!isset($files['error']) || is_array($files['error'])){
            $result['info']='上传失败，请使用批量上传方法';
            return $result;
        }

        // 系统检测是否上传成功
        if($files['error']!==0 || $files['size']===0){
            $result['info']=$this->error[$files['error']]?:'上传失败';
            return $result;
        }
        // 获取扩展名、检测文件类型、定义文件新名称
        $file_extra=pathinfo($files['name'],PATHINFO_EXTENSION);
        $check_file_type_result=$this->checkFileType($file_extra);
        if(!$check_file_type_result){
            $result['info']=$this->error[5];
            return $result;
        }
        $file_name=uniqid().'.'.$file_extra;
        // 获取上传路径、检测上传路径
        $sub_path_type=$this->sub_path_type;
        switch ($sub_path_type) {
            case 1:
                $sub_path=date('Ymd/');
                break;
            
            case 2:
                $sub_path=date('Y/m/d/');
                break;
            
                default:
                $sub_path='';
                break;
        }
        // 文件上传路径
        $uploads_path=$this->root_path.'/'.$sub_path;
        $ret=$this->checkUploadsPath($uploads_path);
        if(!$ret){
            $result['info']='上传失败，上传目录创建失败';
            return $result;
        }
        // 文件全路径
        $file_full_name=$uploads_path.$file_name;
        // 上传文件
        $ret=move_uploaded_file($files['tmp_name'],$file_full_name);
        if($ret){
            $result['status']=1;
            $result['info']='上传成功';
            $result['file_ext']=$file_extra;
            $result['file_name']=$file_name;
            $result['file_path']=$sub_path.$file_name;
        }
        return $result;
    }
}
